package c15IO;

import java.io.Externalizable;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamException;
import java.io.Serializable;

public class 自定义序列化之Externalizable {

	public static void main(String[] args) {
		String fn = "per.ext";
		ObjectInputStream ois = null;
		ObjectOutputStream oos = null;
		try {
			oos = new ObjectOutputStream(new FileOutputStream(fn));
			PersonExt p = new PersonExt("asdfg", 21);
			oos.writeObject(p);
			ois = new ObjectInputStream(new FileInputStream(fn));
			System.err.println(ois.readObject());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

//没有实现Externalizable的基类
class P2 {
	//P类必须提供无参构造器！如果没有定义有参构造器，可以不用显式定义无参构造器，
	//因为系统会自动定义一个无参构造器！去掉这个无参构造器，下面反序列化时会抛异常！
	public P2() {
	}

	public P2(String name, int age) {
	}
}

//基类
class Person2 extends P2 implements Externalizable {
	//为简单测试起见，属性定义为可见的
	protected String name;
	protected int age;

	public Person2() {
	}

	public Person2(String name, int age) {
		super(name, age);
		this.name = name;
		this.age = age;
	}

	@Override
	public String toString() {
		//用反射来取得类名，子类就不用重新这个方法了！
		return this.getClass().getSimpleName() + "[name=" + name + ", age=" + age + "]";
	}

	@Override
	//与Serializable方式的writeObject方法体基本一样！！
	public void writeExternal(ObjectOutput oo) throws IOException {
		System.err.println("writeObject");
		System.err.println("writeObject [name=" + name + ", age=" + age + "]");
		oo.writeObject(new StringBuffer(name).reverse());
		oo.writeInt(age);
	}

	@Override
	//与Serializable方式的readObject方法体基本一样！！
	public void readExternal(ObjectInput oi) throws IOException,
			ClassNotFoundException {
		System.err.println("readObject");
		this.name = ((StringBuffer) oi.readObject()).reverse().toString();
		this.age = oi.readInt();
	}
}

//继承Person2后，这个类可以不用再实现Externalizable接口
class PersonExt extends Person2 {
	private static final long serialVersionUID = 1L;

	//@@与实现Serializable方式不同，这种方式必须提供一个无参构造器，在反序列化时要用到！！！
	public PersonExt() {
		System.err.println("PersonExt()");
	}

	public PersonExt(String name, int age) {
		super(name, age);
		this.name = name;
		this.age = age;
	}

}
